﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Security;

using Bricks.Component.Utils;
using Bricks.Business.Models;
using Bricks.Business.Models.FlowProcess;
using Bricks.Business.Models.Receipt;
using Bricks.Site.Models;
using Bricks.Business.Data.Repositories.FlowProcess;
using Bricks.Business.Data.Repositories.Receipt;
using System.Collections;
using System.Xml;
using Bricks.Business.Service;
using Bricks.Business.Models.AlterManagement;
using System.Configuration;
using Bricks.Business.Models.Account;


namespace ChiDao.Business.Service.Impl
{
    [Export(typeof(IFlowUtilsService))]
    public class FlowUtilsService : IFlowUtilsService
    {
        #region 属性
        [Import]
        protected IAlterService AlterService { get; set; }
        [Import]
        public IAlterOrderService AlterOrderService { get; set; }
        [Import]
        public IExpenseService ExpenseService { get; set; }
        [Import]
        public ITotalMaintenanceService TotalMaintenanceService { get; set; }
        [Import]
        protected IBaklogTaskRepository BaklogTaskRepository { get; set; }
        [Import]
        protected IFlowRepository FlowRepository { get; set; }
        [Import]
        protected IFlowNodeRepository FlowNodeRepository { get; set; }
        [Import]
        protected IProcessedTaskRepository ProcessedTaskRepository { get; set; }
        [Import]
        protected IFlowGraphNodeRepository FlowGraphNodeRepository { get; set; }
        [Import]
        protected ICompleteFlowNodeRepository CompleteFlowNodeRepository { get; set; }
        [Import]
        protected IFlowProcessMessageRepository FlowProcessMessageRepository { get; set; }
        [Import]
        public IOrgInfoService OrgInfoService { get; set; }
        [Import]
        public IUserOrgService UserOrgService { get; set; }
        [Import]
        public IUserInfoService UserInfoService { get; set; }
        #endregion

        #region 公共函数
        public object ExecuteCommand(string command, System.Collections.Hashtable paraList)
        {
            object result = null;
            switch (command)
            {
                //case "IsFNode":
                //    result = IsFNode(paraList);
                //    break;
                //case "GetNextNodeForSubProcessNodeType":
                //    result = GetNextNodeForSubProcessNodeType(paraList);
                //    break;
                //case "GetProcessPersonForAlter":
                //    result = GetProcessPersonForAlter(paraList);
                //    break;
                //case "GetNextNodeForAlterOrder":
                //    result = GetNextNodeForAlterOrder(paraList);
                //    break;
                //case "GetRequestDepartmentAndUser":
                //    result = GetRequestDepartmentAndUser(paraList);
                //    break;

                case "GetProcessPersonForParentDepartment":
                    result = GetProcessPersonForParentDepartment(paraList);
                    break;
                case "GetProcessPersonForCurrentDepartmentHandoutAdmin":
                    result = GetProcessPersonForCurrentDepartmentHandoutAdmin(paraList);
                    break;
                case "GetNextNodeForAlter":
                    result = GetNextNodeForAlter(paraList);
                    break;
            }
            return result;
        }

        #region 暂时没用到的函数
        private bool IsFNode(Hashtable para)
        {
            bool isFinish = false;
            string recordID = para["RecordID"].ToString();
            string[] paraArr = para["functionParam"].ToString().Split(';');
            string[] codeArr = paraArr[0].TrimStart('[').TrimEnd(']').Split(',');
            IQueryable<CompleteFlowNode> completeFlowNodeList = CompleteFlowNodeRepository.Entities.Where(r => r.RecordID == recordID && r.SpecState == 0 && codeArr.Contains(r.NodeCode));
            if (paraArr[1].ToLower() == "and")
            {
                IQueryable<CompleteFlowNode> receiptProcessNodeInfoList = CompleteFlowNodeRepository.Entities.Where(r => r.RecordID == recordID && r.SpecState == 0 && paraArr[0].Contains(r.NodeCode));
                if (completeFlowNodeList.Count() == codeArr.Length)
                {
                    isFinish = true;
                }
            }
            else
            {
                if (completeFlowNodeList.Count() > 0)
                {
                    isFinish = true;
                }
            }
            return isFinish;
        }

        private string GetNextNodeForSubProcessNodeType(Hashtable para)
        {
            Hashtable paraSub = new Hashtable();
            paraSub.Add("RecordID", para["RecordID"]);
            string[] paraArr = para["functionParam"].ToString().Split('|');
            paraSub.Add("functionParam", paraArr[0]);
            bool isFinish = IsFNode(paraSub);
            if (isFinish)
            {
                return paraArr[1].TrimStart('[').TrimEnd(']');
            }
            else
            {
                return paraArr[2].TrimStart('[').TrimEnd(']');
            }
        }

        private string GetNextNodeForAlterOrder(Hashtable para)
        {
            string[] paraArr = para["functionParam"].ToString().Split(';');
            AlterOrderView alterOrderView = null;
            if (para.ContainsKey("IsGetBusinessData"))
            {
                alterOrderView = AlterOrderService.GetAlterOrderByID(para["RecordID"].ToString());
            }
            else
            {
                alterOrderView = AlterOrderService.GetAlterOrderBackupByCondition(para["RecordID"].ToString(), para["SourceNodeCode"].ToString(), para["ProcessUserDepartment"].ToString(), para["ProcessUser"].ToString());
            }
            if (alterOrderView.AlterType == paraArr[0])
            {
                return paraArr[1].TrimStart('[').TrimEnd(']');
            }
            else
            {
                return paraArr[2].TrimStart('[').TrimEnd(']');
            }
        }

        //为流程获取能做申请的部门和人
        private string GetRequestDepartmentAndUser(Hashtable para)
        {
            string requestDepartmentAndUserStr = string.Empty;
            if (para["functionParam"].ToString() == "AlterOne")
            {
                requestDepartmentAndUserStr = ConfigurationManager.AppSettings["RequestDepartmentListForAlterOne"] as string;
            }
            else if (para["functionParam"].ToString() == "AlterTwo")
            {
                requestDepartmentAndUserStr = ConfigurationManager.AppSettings["RequestDepartmentListForAlterTwo"] as string;
            }
            else if (para["functionParam"].ToString() == "AlterThree")
            {
                requestDepartmentAndUserStr = ConfigurationManager.AppSettings["RequestDepartmentListForAlterThree"] as string;
            }
            else if (para["functionParam"].ToString() == "AlterOrderOne")
            {
                requestDepartmentAndUserStr = ConfigurationManager.AppSettings["RequestDepartmentListForAlterOrderOne"] as string;
            }
            else if (para["functionParam"].ToString() == "Expense")
            {
                requestDepartmentAndUserStr = ConfigurationManager.AppSettings["RequestDepartmentListForExpense"] as string;
            }
            return requestDepartmentAndUserStr;
        }
        #endregion

        //获取当前部门的上级部门的审批人
        private string GetProcessPersonForParentDepartment(Hashtable para)
        {
            string defaultProcessPerson = string.Empty;
            string orgCode = para["OrgCode"].ToString();
            OrgInfo currentOrgInfo = OrgInfoService.Orgs.SingleOrDefault(o => o.OrgCode == orgCode);
            if (currentOrgInfo != null)
            {
                OrgInfo parentOrgInfo = OrgInfoService.Orgs.SingleOrDefault(o => o.ID == currentOrgInfo.PID);
                if (parentOrgInfo != null)
                {
                    IQueryable<UserInfo> lstUserInfo = from u in UserInfoService.Users
                                                       join uo in UserOrgService.UserOrgs
                                                       on u.ID equals uo.UserID
                                                       where uo.OrgID == parentOrgInfo.ID && uo.IsFlowApprovalPerson == true
                                                       select u;
                    foreach (UserInfo userInfo in lstUserInfo)
                    {
                        defaultProcessPerson += parentOrgInfo.OrgCode + "|" + userInfo.UserName + ",";
                    }
                }
            }
            if (!string.IsNullOrEmpty(defaultProcessPerson))
            {
                defaultProcessPerson = defaultProcessPerson.Trim(',');
            }
            return defaultProcessPerson;
        }

        //获取当前部门的上级部门的分发管理员
        private string GetProcessPersonForCurrentDepartmentHandoutAdmin(Hashtable para)
        {
            string defaultProcessPerson = string.Empty;
            string orgCode = para["OrgCode"].ToString();
            OrgInfo currentOrgInfo = OrgInfoService.Orgs.SingleOrDefault(o => o.OrgCode == orgCode);
            if (currentOrgInfo != null)
            {
                IQueryable<UserInfo> lstUserInfo = from u in UserInfoService.Users
                                                   join uo in UserOrgService.UserOrgs
                                                   on u.ID equals uo.UserID
                                                   where uo.OrgID == currentOrgInfo.ID && uo.IsHandoutAdmin == true
                                                   select u;
                foreach (UserInfo userInfo in lstUserInfo)
                {
                    defaultProcessPerson += orgCode + "|" + userInfo.UserName + ",";
                }
            }
            if (!string.IsNullOrEmpty(defaultProcessPerson))
            {
                defaultProcessPerson = defaultProcessPerson.Trim(',');
            }
            return defaultProcessPerson;
        }

        //变更申请判断条件分支获取下一节点
        private string GetNextNodeForAlter(Hashtable para)
        {
            string[] paraArr = para["functionParam"].ToString().Split(';');
            AlterView alterView = null;
            if (para.ContainsKey("IsGetBusinessData"))
            {
                alterView = AlterService.GetAlterByID(para["RecordID"].ToString());
            }
            else
            {
                alterView = AlterService.GetAlterBackupByCondition(para["RecordID"].ToString(), para["SourceNodeCode"].ToString(), para["ProcessUserDepartment"].ToString(), para["ProcessUser"].ToString());
            }
            if (alterView.AlterType == paraArr[0])
            {
                return paraArr[1].TrimStart('[').TrimEnd(']');
            }
            else
            {
                return paraArr[2].TrimStart('[').TrimEnd(']');
            }
        }
        #endregion


        #region 撤回
        public void Withdraw(FlowNodeView withdrawNode, string flowCode, string recordID, string processUserDepartment, DateTime requestDate, List<FlowNodeView> lstCirculationNode, Dictionary<string, List<FlowNodeView>> dicConditionAndCirculationNode)
        {
            //根据撤回到的节点Code从节点完成表获取完成节点
            CompleteFlowNode completeFlowNode = CompleteFlowNodeRepository.Entities.Single(c => c.RecordID == recordID && c.NodeCode == withdrawNode.NodeCode);

            //拼接流转节点Code,删除待办，处理流程消息
            string circulationNodeStr = string.Empty;
            foreach (FlowNodeView flowNodeView in lstCirculationNode)
            {
                circulationNodeStr += "'" + flowNodeView.NodeCode + "',";
            }
            circulationNodeStr = circulationNodeStr.Trim(',');
            BaklogTaskRepository.ExeSqlCommon("DELETE FROM BaklogTasks WHERE RecordID='" + recordID + "' AND CurrentFlowNodeCode IN (" + circulationNodeStr + ")");
            FlowProcessMessageRepository.ExeSqlCommon("UPDATE FlowProcessMessages SET State=1 WHERE RecordID='" + recordID + "' AND FlowNodeCode IN (" + circulationNodeStr + ") AND ProcessType IN ('1','2','5');");

            //处理单据的业务数据
            ProcessReceiptForWithdraw(flowCode, withdrawNode, recordID, circulationNodeStr);

            //添加待办
            AddBaklogTaskForWithdraw(completeFlowNode.NodeProcessDepartmentPerson, flowCode, recordID, requestDate, withdrawNode.NodeCode, withdrawNode.NodeLevel);

            //如果撤回到的节点有or关系的兄弟节点，那么这些节点也要生成待办信息
            XmlDocument docBaklogTask = new System.Xml.XmlDocument();
            docBaklogTask.LoadXml(withdrawNode.NodeXML);
            XmlNode brotherNode = docBaklogTask.SelectSingleNode("NodeXML/brotherCell/orCellList");
            if (brotherNode != null)
            {
                Guid flowID = FlowRepository.Entities.Single(f => f.FlowCode == flowCode).ID;
                string[] brotherNodeCodeArr = brotherNode.InnerText.Split(',');
                foreach (string nodeCode in brotherNodeCodeArr)
                {
                    FlowNode flowNode = FlowNodeRepository.Entities.Single(f => f.PID == flowID && f.NodeCode == nodeCode);
                    string defaultProcessPerson = GetDefaultProcessPerson(flowNode.NodeXML, processUserDepartment);
                    AddBaklogTaskForWithdraw(defaultProcessPerson, flowCode, recordID, requestDate, flowNode.NodeCode, flowNode.NodeLevel);
                }
            }

            //删除完成节点表和流程构造表数据
            DeleteCompleteFlowNodeAndFlowGraphNode(recordID, withdrawNode.NodeCode, dicConditionAndCirculationNode);

            //删除已办信息
            DeleteProcessedTask(recordID, withdrawNode.NodeCode);
        }

        /// <summary>
        /// 处理单据的业务数据
        /// </summary>
        /// <param name="flowCode">流程编码</param>
        /// <param name="nodeType">节点的类型</param>
        /// <param name="recordID">单据ID</param>
        /// <param name="nodeCode">要撤回到的节点的编码</param>
        /// <param name="nodeCodeStr">流转节点编码字符串</param>
        /// <returns></returns>      
        private void ProcessReceiptForWithdraw(string flowCode, FlowNodeView withdrawNode, string recordID, string nodeCodeStr)
        {
            switch (flowCode)
            {
                case "AlterOne":
                case "AlterTwo":
                case "AlterThree":
                    if (withdrawNode.NodeType == 1)
                    {
                        AlterService.WithdrawOrBackAlterForRequestNode(recordID, withdrawNode.NodeCode);
                    }
                    else
                    {
                        AlterService.WithdrawOrBackAlterForOtherNode(recordID, withdrawNode.NodeCode, nodeCodeStr);
                        //取最后一个发送的节点作为业务数据
                        AlterView alterView = AlterService.GetAlterBackupByAlterID(recordID);
                        List<AlterBillView> lstAlterBillView = AlterService.GetAlterBillBackupList(alterView.AlterID, alterView.AssociatedNodeCode, alterView.LastUpdateUserDepartment, alterView.LastUpdateUser);
                        AlterService.SaveAlter(alterView, lstAlterBillView);
                    }
                    break;
                case "AlterOrderOne":
                    if (withdrawNode.NodeType == 1)
                    {
                        AlterOrderService.WithdrawOrBackAlterOrderForRequestNode(recordID, withdrawNode.NodeCode);
                    }
                    else
                    {
                        AlterOrderService.WithdrawOrBackAlterOrderForOtherNode(recordID, withdrawNode.NodeCode, nodeCodeStr);
                        //取最后一个发送的节点作为业务数据
                        AlterOrderView alterOrderView = AlterOrderService.GetAlterOrderBackupByAlterOrderID(recordID);
                        List<AlterOrderBillView> lstAlterOrderBillView = AlterOrderService.GetAlterOrderBillBackupList(alterOrderView.AlterOrderID, alterOrderView.AssociatedNodeCode, alterOrderView.LastUpdateUserDepartment, alterOrderView.LastUpdateUser);
                        AlterOrderService.SaveAlterOrder(alterOrderView, lstAlterOrderBillView);
                    }
                    break;
                case "Expense":
                    if (withdrawNode.NodeType == 1)
                    {
                        ExpenseService.WithdrawOrBackExpenseForRequestNode(recordID, withdrawNode.NodeCode);
                    }
                    else
                    {
                        ExpenseService.WithdrawOrBackExpenseForOtherNode(recordID, withdrawNode.NodeCode, nodeCodeStr);
                        //取最后一个发送的节点作为业务数据
                        ExpenseView expenseView = ExpenseService.GetExpenseBackupByExpenseID(recordID);
                        List<ConstructionContractEepenseBillView> saveList = new List<ConstructionContractEepenseBillView>();
                        if (expenseView.ContractSource == "Construction")
                        {
                            saveList = ExpenseService.GetBillBackupList(expenseView.ExpenseID, expenseView.AssociatedNodeCode, expenseView.LastUpdateUserDepartment, expenseView.LastUpdateUser);
                        }
                        ExpenseService.SaveExpense(expenseView, saveList);
                    }
                    break;
            }
        }

        /// <summary>
        /// 添加待办
        /// </summary>
        /// <param name="processDepartmentAndPersonStr">处理人拼接字符串</param>
        /// <param name="flowCode">流程编码</param>
        /// <param name="recordID">单据ID</param>
        /// <param name="requestPerson">申请人</param>
        /// <param name="nodeCode">节点Code</param>
        /// <param name="nodeLevel">节点级别</param>
        private void AddBaklogTaskForWithdraw(string processDepartmentAndPersonStr, string flowCode, string recordID, DateTime requestDate, string nodeCode, int nodeLevel)
        {
            string[] processDepartmentAndPersonArr = processDepartmentAndPersonStr.Split(',');
            foreach (string processDepartmentAndPerson in processDepartmentAndPersonArr)
            {
                string[] subProcessDepartmentAndPersonArr = processDepartmentAndPerson.Split('|');
                BaklogTask add = new BaklogTask();
                add.ID = GuidHelper.NewGuid();
                add.RecordID = recordID;
                add.TaskType = flowCode;
                add.RequestDate = requestDate;
                add.CurrentFlowNodeCode = nodeCode;
                add.CurrentProcessPersonDepartment = subProcessDepartmentAndPersonArr[0];
                add.CurrentProcessPerson = subProcessDepartmentAndPersonArr[1];
                add.NodeLevel = nodeLevel;
                BaklogTaskRepository.Insert(add);
            }
        }

        /// <summary>
        /// 获取缺省处理人和部门
        /// </summary>
        /// <param name="docPerson">节点xml文档</param>
        /// <param name="recordID">单据ID</param>
        /// <returns></returns>
        private string GetDefaultProcessPerson(string nodeXML, string processUserDepartment)
        {
            string defaultProcessPerson = string.Empty;
            XmlDocument docPerson = new XmlDocument();
            docPerson.LoadXml(nodeXML);
            XmlNode personNode = docPerson.SelectSingleNode("NodeXML/defaultProcessPerson");
            if (personNode != null)
            {
                string processPersonGetType = personNode.SelectSingleNode("getType").InnerText;
                if (processPersonGetType == "value")
                {
                    defaultProcessPerson = personNode.SelectSingleNode("presonList").InnerText;
                }
                else
                {
                    string functionName = personNode.SelectSingleNode("functionName").InnerText;
                    Hashtable para = new Hashtable();
                    para.Add("OrgCode", processUserDepartment);
                    XmlNode paraNode = personNode.SelectSingleNode("functionParam");
                    if (paraNode != null)
                    {
                        para.Add(paraNode.Name, paraNode.InnerText);
                    }
                    defaultProcessPerson = ExecuteCommand(functionName, para) as string;
                }
            }
            return defaultProcessPerson;
        }

        /// <summary>
        /// 删除流程构造表和节点完成表
        /// </summary>
        /// <param name="recordID">单据ID</param>
        /// <param name="withdrawNodeCode">撤回到的节点编码</param>
        /// <param name="dicConditionAndCirculationNode">存储所有的中间经过的条件节点和流转节点的字典</param>
        private void DeleteCompleteFlowNodeAndFlowGraphNode(string recordID, string withdrawNodeCode, Dictionary<string, List<FlowNodeView>> dicConditionAndCirculationNode)
        {
            IQueryable<FlowGraphNode> flowGraphNodeList = FlowGraphNodeRepository.Entities.Where(f => f.RecordID == recordID);
            string completeFlowNodeStr = "'" + withdrawNodeCode + "',";
            string flowGraphNodeIDStr = string.Empty;
            foreach (List<FlowNodeView> nodeList in dicConditionAndCirculationNode.Values)
            {
                for (int i = 0; i < nodeList.Count; i++)
                {
                    //拼接要删除的条件完成节点的Code
                    if (i < nodeList.Count - 1)
                    {
                        completeFlowNodeStr += "'" + nodeList[i].NodeCode + "',";
                    }

                    //拼接要删除的流程节点的ID
                    string pathStartNodeCode = withdrawNodeCode;
                    if (i > 0)
                    {
                        pathStartNodeCode = nodeList[i - 1].NodeCode;
                    }
                    string pathEndNodeCode = nodeList[i].NodeCode;
                    FlowGraphNode deleteFlowGraphNode = flowGraphNodeList.Where(f => f.PathStartNodeCode == pathStartNodeCode && f.PathEndNodeCode == pathEndNodeCode && f.ActionType == 0).OrderByDescending(f => f.OrderNo).FirstOrDefault();
                    if (deleteFlowGraphNode != null)
                    {
                        flowGraphNodeIDStr += "'" + deleteFlowGraphNode.ID + "',";
                    }
                }
            }

            CompleteFlowNodeRepository.ExeSqlCommon("DELETE FROM CompleteFlowNodes WHERE RecordID='" + recordID + "' AND NodeCode IN (" + completeFlowNodeStr.Trim(',') + ")");
            if (flowGraphNodeIDStr != string.Empty)
            {
                FlowGraphNodeRepository.ExeSqlCommon("DELETE FROM FlowGraphNodes WHERE ID IN (" + flowGraphNodeIDStr.Trim(',') + ")");
            }
        }

        /// <summary>
        /// 删除已办信息
        /// </summary>
        /// <param name="recordID">单据ID</param>
        /// <param name="withdrawNodeCode">撤回到的流程节点的编码</param>
        private void DeleteProcessedTask(string recordID, string withdrawNodeCode)
        {
            string processedTaskIDStr = string.Empty;
            IQueryable<ProcessedTask> processedTaskList = ProcessedTaskRepository.Entities.Where(p => p.RecordID == recordID && p.CurrentProcessNodeCode == withdrawNodeCode).OrderByDescending(p => p.AddDate);
            foreach (ProcessedTask processedTask in processedTaskList)
            {
                if (processedTask.HandleState != "1")
                {
                    break;
                }
                processedTaskIDStr += "'" + processedTask.ID + "',";
            }
            if (processedTaskIDStr != string.Empty)
            {
                ProcessedTaskRepository.ExeSqlCommon("DELETE FROM ProcessedTasks WHERE ID IN (" + processedTaskIDStr.Trim(',') + ")");
            }
        }
        #endregion

        public void Reminders(string recordID, string flowCode, string userName)
        {
            IQueryable<BaklogTask> baklogTasks = BaklogTaskRepository.Entities.Where(b => b.RecordID == recordID);
            List<BaklogTaskView> lstBaklogTaskView = new List<BaklogTaskView>();
            foreach (BaklogTask baklogTask in baklogTasks)
            {
                lstBaklogTaskView.Add(new BaklogTaskView()
                {
                    ID = baklogTask.ID,
                    RecordID = baklogTask.RecordID,
                    TaskType = baklogTask.TaskType,
                    RequestDate = baklogTask.RequestDate,
                    CurrentFlowNodeCode = baklogTask.CurrentFlowNodeCode,
                    CurrentProcessPersonDepartment = baklogTask.CurrentProcessPersonDepartment,
                    CurrentProcessPerson = baklogTask.CurrentProcessPerson,
                    NodeLevel = baklogTask.NodeLevel
                });
            }
            foreach (BaklogTaskView baklogTask in lstBaklogTaskView)
            {
                FlowProcessMessage flowProcessMessage = FlowProcessMessageRepository.Entities.SingleOrDefault(f => f.RecordID == recordID && f.FlowNodeCode == baklogTask.CurrentFlowNodeCode && f.ProcessUserDepartment == baklogTask.CurrentProcessPersonDepartment && f.ProcessUser == baklogTask.CurrentProcessPerson && f.ProcessType == "5" && f.State == 0);
                if (flowProcessMessage != null)
                {
                    flowProcessMessage.RemindersNum = flowProcessMessage.RemindersNum + 1;
                    if (!("," + flowProcessMessage.SponsorUser + ",").Contains("," + userName + ","))
                    {
                        flowProcessMessage.SponsorUser = flowProcessMessage.SponsorUser + "," + userName;
                    }
                    flowProcessMessage.LastUpdateTime = DateTime.Now;
                    FlowProcessMessageRepository.Update(flowProcessMessage);
                }
                else
                {
                    FlowProcessMessage addFlowProcessMessage = new FlowProcessMessage()
                    {
                        ID = GuidHelper.NewGuid(),
                        RecordID = recordID,
                        FlowCode = flowCode,
                        FlowNodeCode = baklogTask.CurrentFlowNodeCode,
                        ProcessUserDepartment = baklogTask.CurrentProcessPersonDepartment,
                        ProcessUser = baklogTask.CurrentProcessPerson,
                        SponsorUser = userName,
                        RemindersNum = 1,
                        ProcessType = "5",
                        State = 0,
                        LastUpdateUser = userName,
                        LastUpdateTime = DateTime.Now
                    };
                    FlowProcessMessageRepository.Insert(addFlowProcessMessage);
                }
            }
        }

        public void Cancel(string flowCode, string processPerson, string recordID)
        {
            //获取待办的当前节点Code，获取当前节点
            IQueryable<BaklogTask> baklogTasks = BaklogTaskRepository.Entities.Where(b => b.CurrentProcessPerson == processPerson && b.RecordID == recordID);
            string currentProcessNodeCode = baklogTasks.First().CurrentFlowNodeCode;
            Flow flow = FlowRepository.Entities.Where(p => p.FlowCode == flowCode).First();
            FlowNode currentFlowNode = FlowNodeRepository.Entities.Where(p => p.PID == flow.ID && p.NodeCode == currentProcessNodeCode).First();

            //获取所有待办，并删除
            baklogTasks = BaklogTaskRepository.Entities.Where(b => b.RecordID == recordID);
            List<Guid> idList = new List<Guid>();
            foreach (BaklogTask baklogTask in baklogTasks)
            {
                idList.Add(baklogTask.ID);
            }
            foreach (Guid id in idList)
            {
                BaklogTaskRepository.Delete(id);
            }

            //添加已办
            ProcessedTask processedTask = new ProcessedTask()
            {
                ID = Guid.NewGuid(),
                RecordID = recordID,
                FlowCode = flowCode,
                CurrentProcessNodeCode = currentFlowNode.NodeCode,
                CurrentProcessNodeName = currentFlowNode.NodeName,
                ApprovalOpinion = "终止",
                CurrentProcessPerson = processPerson,
                ProcessTime = DateTime.Now,
                HandleState = "3"
            };
            ProcessedTaskRepository.Insert(processedTask);

            //发终止消息
            List<CompleteFlowNodeView> completeFlowNodeViewList = new List<CompleteFlowNodeView>();
            IQueryable<CompleteFlowNode> completeFlowNodeList = CompleteFlowNodeRepository.Entities.Where(c => c.RecordID == recordID && c.NodeLevel == 1 && c.NodeType != 2);
            foreach (CompleteFlowNode completeFlowNode in completeFlowNodeList)
            {
                completeFlowNodeViewList.Add(new CompleteFlowNodeView()
                {
                    ID = completeFlowNode.ID,
                    RecordID = completeFlowNode.RecordID,
                    NodeCode = completeFlowNode.NodeCode,
                    NodeName = completeFlowNode.NodeName,
                    NodeProcessDepartmentPerson = completeFlowNode.NodeProcessDepartmentPerson,
                    PreNodeCode = completeFlowNode.PreNodeCode,
                    ParentNodeCode = completeFlowNode.ParentNodeCode,
                    NodeLevel = completeFlowNode.NodeLevel,
                    NodeType = completeFlowNode.NodeType,
                    NodeSubType = completeFlowNode.NodeSubType,
                    SpecState = completeFlowNode.SpecState
                });
            }
            foreach (CompleteFlowNodeView completeFlowNodeView in completeFlowNodeViewList)
            {
                string[] processDepartmentAndPersonArr = completeFlowNodeView.NodeProcessDepartmentPerson.Split(',');
                foreach (string processDepartmentAndPerson in processDepartmentAndPersonArr)
                {
                    string[] subProcessDepartmentAndPersonArr = processDepartmentAndPerson.Split('|');
                    FlowProcessMessage flowProcessMessage = new FlowProcessMessage()
                    {
                        ID = GuidHelper.NewGuid(),
                        RecordID = recordID,
                        FlowCode = flowCode,
                        FlowNodeCode = completeFlowNodeView.NodeCode,
                        ProcessUserDepartment = subProcessDepartmentAndPersonArr[0],
                        ProcessUser = subProcessDepartmentAndPersonArr[1],
                        SponsorUser = processPerson,
                        ProcessType = "3",
                        State = 0,
                        LastUpdateUser = processPerson,
                        LastUpdateTime = DateTime.Now
                    };
                    FlowProcessMessageRepository.Insert(flowProcessMessage);
                }
            }

            // 流程终止之后删除没有发送的过程数据
            switch (flowCode)
            {
                case "AlterOne":
                case "AlterTwo":
                case "AlterThree":
                    AlterService.DeleteAlterProcessData(recordID);
                    break;
                case "AlterOrderOne":
                    AlterOrderService.DeleteAlterOrderProcessData(recordID);
                    break;
                case "Expense":
                    ExpenseService.DeleteExpenseProcessData(recordID);
                    break;
            }
        }

        #region 构造流程图
        /// <summary>
        /// 节点颜色：完成绿色，终止红色，当前蓝色,分发到子流程的节点不是真正的完成黄色
        /// 连线颜色：流转绿色，逐级回退红色，跨级回退黄色,传阅蓝色
        /// </summary>
        /// <param name="flowCode">流程Code</param>
        /// <param name="recordID">单据ID</param>
        /// <param name="handleState">单据状态</param>
        /// <returns></returns>
        public WorkFlowView GenerateGraph(string flowCode, string recordID, string handleState)
        {
            //解析节点信息，添加所有的节点和连线
            WorkFlowView workFlowView = new WorkFlowView();
            AddAllNodeAndLink(flowCode, workFlowView);

            if (!string.IsNullOrEmpty(handleState))
            {
                //设置节点的颜色
                SetNodeColor(workFlowView, recordID, handleState);

                //设置连线的颜色
                SetLinkColor(workFlowView, recordID);

                //添加催办节点
                IQueryable<FlowProcessMessage> flowProcessMessageList = FlowProcessMessageRepository.Entities.Where(f => f.RecordID == recordID && f.ProcessType == "5" && f.State == 0);
                Dictionary<string, int?> dicReminders = new Dictionary<string, int?>();
                foreach (FlowProcessMessage flowProcessMessage in flowProcessMessageList)
                {
                    if (dicReminders.ContainsKey(flowProcessMessage.FlowNodeCode))
                    {
                        if (flowProcessMessage.RemindersNum > dicReminders[flowProcessMessage.FlowNodeCode])
                        {
                            dicReminders[flowProcessMessage.FlowNodeCode] = flowProcessMessage.RemindersNum;
                        }
                    }
                    else
                    {
                        dicReminders.Add(flowProcessMessage.FlowNodeCode, flowProcessMessage.RemindersNum);
                    }
                }
                foreach (KeyValuePair<string, int?> keyValue in dicReminders)
                {
                    WorkFlowNodeView workFlowNodeView = workFlowView.lstWorkFlowNodeView.SingleOrDefault(n => n.NodeCode == keyValue.Key);
                    WorkFlowNodeView remindersWorkFlowNodeView = new WorkFlowNodeView();
                    remindersWorkFlowNodeView.NodeCode = workFlowNodeView.NodeCode;
                    remindersWorkFlowNodeView.NodeName = "催办" + keyValue.Value.ToString() + "次";
                    remindersWorkFlowNodeView.LocationX = workFlowNodeView.LocationX + workFlowNodeView.Width - 20;
                    remindersWorkFlowNodeView.LocationY = workFlowNodeView.LocationY - 15;
                    workFlowView.lstRemindersWorkFlowNodeView.Add(remindersWorkFlowNodeView);
                }
            }

            return workFlowView;
        }

        private void AddAllNodeAndLink(string flowCode, WorkFlowView workFlowView)
        {
            Flow flow = FlowRepository.Entities.Where(p => p.FlowCode == flowCode).First();
            IQueryable<FlowNode> flowNodeList = FlowNodeRepository.Entities.Where(p => p.PID == flow.ID).OrderBy(p => p.OrderNo);
            foreach (FlowNode processNode in flowNodeList)
            {
                WorkFlowNodeView workFlowNodeView = new WorkFlowNodeView();
                workFlowNodeView.NodeCode = processNode.NodeCode;
                workFlowNodeView.NodeName = processNode.NodeName;
                workFlowNodeView.NodeType = processNode.NodeType;
                workFlowNodeView.LocationX = processNode.LocationX;
                workFlowNodeView.LocationY = processNode.LocationY;
                workFlowNodeView.Width = processNode.Width;
                workFlowNodeView.Height = processNode.Height;
                workFlowNodeView.Shape = processNode.Shape;
                workFlowNodeView.NodeColor = "";
                workFlowView.lstWorkFlowNodeView.Add(workFlowNodeView);

                if (!string.IsNullOrEmpty(processNode.NodeXML))
                {
                    XmlDocument docNextNode = new XmlDocument();
                    docNextNode.LoadXml(processNode.NodeXML);
                    XmlNode nextNode = docNextNode.SelectSingleNode("NodeXML/nextCell");
                    if (nextNode != null)
                    {
                        foreach (XmlNode node in nextNode.ChildNodes)
                        {
                            WorkFlowNodeLineView workFlowNodeLineView = new WorkFlowNodeLineView();
                            workFlowNodeLineView.NodeCode = processNode.NodeCode;
                            workFlowNodeLineView.NextNodeCode = node.InnerText;
                            workFlowNodeLineView.LineColor = "";
                            if (node.Attributes.Count > 0)
                            {
                                if (node.Attributes["title"] != null)
                                {
                                    workFlowNodeLineView.LineTitle = node.Attributes["title"].Value;
                                }
                                if (node.Attributes["linePointX"] != null)
                                {
                                    workFlowNodeLineView.LinePointX = Convert.ToInt32(node.Attributes["linePointX"].Value);
                                }
                                if (node.Attributes["linePointY"] != null)
                                {
                                    workFlowNodeLineView.LinePointY = Convert.ToInt32(node.Attributes["linePointY"].Value);
                                }
                            }
                            workFlowNodeLineView.CirculationNum = 0;
                            workFlowView.lstWorkFlowNodeLineView.Add(workFlowNodeLineView);
                        }
                    }
                }
            }
        }

        private void SetNodeColor(WorkFlowView workFlowView, string recordID, string handleState)
        {
            //设置Start节点颜色
            WorkFlowNodeView workFlowNodeFirst = workFlowView.lstWorkFlowNodeView.Where(n => n.NodeCode == "Start").First();
            workFlowNodeFirst.NodeColor = "fillColor=green;";//绿

            //设置完成节点的颜色
            IQueryable<CompleteFlowNode> completeFlowNodeList = CompleteFlowNodeRepository.Entities.Where(c => c.RecordID == recordID);
            foreach (CompleteFlowNode completeFlowNode in completeFlowNodeList)
            {
                WorkFlowNodeView workFlowNode = workFlowView.lstWorkFlowNodeView.SingleOrDefault(n => n.NodeCode == completeFlowNode.NodeCode);
                if (workFlowNode != null)
                {
                    if (completeFlowNode.SpecState == 0)
                    {
                        workFlowNode.NodeColor = "fillColor=green;";//绿
                    }
                    else
                    {
                        workFlowNode.NodeColor = "fillColor=yellow;";//黄
                    }
                }
            }

            //设置当前节点颜色
            if (handleState == "0")
            {
                WorkFlowNodeView workFlowNode = workFlowView.lstWorkFlowNodeView.SingleOrDefault(n => n.NodeType == 1);
                workFlowNode.NodeColor = "fillColor=blue;";//蓝
            }
            else if (handleState == "1" || handleState == "4")
            {
                IQueryable<BaklogTask> baklogTaskList = BaklogTaskRepository.Entities.Where(c => c.RecordID == recordID);
                foreach (BaklogTask baklogTask in baklogTaskList)
                {
                    WorkFlowNodeView workFlowNode = workFlowView.lstWorkFlowNodeView.SingleOrDefault(n => n.NodeCode == baklogTask.CurrentFlowNodeCode);
                    if (workFlowNode != null)
                    {
                        workFlowNode.NodeColor = "fillColor=blue;";//蓝
                    }
                }
            }
            else if (handleState == "2")
            {
                WorkFlowNodeView workFlowNode = workFlowView.lstWorkFlowNodeView.SingleOrDefault(n => n.NodeCode == "End");
                workFlowNode.NodeColor = "fillColor=green;";//绿
            }
            else if (handleState == "3")
            {
                ProcessedTask ProcessedTask = ProcessedTaskRepository.Entities.SingleOrDefault(p => p.RecordID == recordID && p.HandleState == "3");
                WorkFlowNodeView workFlowNode = workFlowView.lstWorkFlowNodeView.SingleOrDefault(n => n.NodeCode == ProcessedTask.CurrentProcessNodeCode);
                if (workFlowNode != null)
                {
                    workFlowNode.NodeColor = "fillColor=red;";//红
                }
            }
        }

        private void SetLinkColor(WorkFlowView workFlowView, string recordID)
        {
            WorkFlowNodeLineView firstWorkFlowNodeLineView = workFlowView.lstWorkFlowNodeLineView.SingleOrDefault(l => l.NodeCode == "Start");
            firstWorkFlowNodeLineView.LineColor = "strokeColor=green;";
            IQueryable<FlowGraphNode> flowGraphNodeList = FlowGraphNodeRepository.Entities.Where(f => f.RecordID == recordID).OrderBy(f => f.OrderNo);
            foreach (FlowGraphNode flowGraphNode in flowGraphNodeList)
            {
                WorkFlowNodeLineView workFlowNodeLineView = workFlowView.lstWorkFlowNodeLineView.SingleOrDefault(l => l.NodeCode == flowGraphNode.PathStartNodeCode && l.NextNodeCode == flowGraphNode.PathEndNodeCode);
                if (workFlowNodeLineView != null)
                {
                    if (flowGraphNode.ActionType == 0)
                    {
                        workFlowNodeLineView.CirculationNum++;
                        workFlowNodeLineView.LineColor = "strokeColor=green;";
                    }
                    else if (flowGraphNode.ActionType == 1)
                    {
                        workFlowNodeLineView.LineColor = "strokeColor=red;";
                    }
                    else if (flowGraphNode.ActionType == 2)
                    {
                        workFlowNodeLineView.LineColor = "strokeColor=yellow;";
                    }
                    else
                    {
                        workFlowNodeLineView.LineColor = "strokeColor=blue;";
                    }
                }
            }

            foreach (WorkFlowNodeLineView workFlowNodeLineView in workFlowView.lstWorkFlowNodeLineView)
            {
                if (workFlowNodeLineView.CirculationNum > 1 && workFlowNodeLineView.LineColor == "strokeColor=green;")
                {
                    if (workFlowNodeLineView.LineTitle != null)
                    {
                        workFlowNodeLineView.LineTitle += "\n" + workFlowNodeLineView.CirculationNum.ToString() + "次";
                    }
                    else
                    {
                        workFlowNodeLineView.LineTitle = workFlowNodeLineView.CirculationNum.ToString() + "次";
                    }
                }
            }
        }
        #endregion
    }
}